package checkers3d.storage;

import java.io.*;
import java.util.*;
import javax.swing.*;
import checkers3d.logic.*;

/**
 *
 * @author Sean Keel
 */
public class DataManagerAccounts {

    /**
     * Saves a player's name and password to an accounts file.
     *
     * @param name The player's username.
     * @param password The player's password.
     */
    static public void addPlayer(Player playerAccount) throws IOException {
        FileWriter fw = new FileWriter("Accounts.txt", true);
        BufferedWriter out = new BufferedWriter(fw);

        // If the player does not exist, write the username and password
        // to the Accounts.txt file.
        if (!doesPlayerExist(playerAccount.getName())){
            DataManagerStats.createIndividualStatistic(playerAccount);
            String playerInfo = new String();
            playerInfo = (playerAccount.getName() + "\t" + playerAccount.getPassword());
            out.write(playerInfo);
            out.newLine();
            JOptionPane.showMessageDialog(null, "The account was successfully created.");
        }
        // If the player does exist, do not add the account and display
        // an error message.
        else
            JOptionPane.showMessageDialog(null, "The account could not be created"
                    + " because\nan account with the name "
                    + playerAccount.getName() + " already exists.");

        out.close();
    }

    /**
     * Removes a player and their password from the accounts file if they exist.
     *
     * @param name The player's username.
     */
    static public void removePlayer(String name) throws FileNotFoundException, IOException{
        if (doesPlayerExist(name)){
            // Make a backup file of the accounts
            createBackupAccountsFile();
            // Delete the accounts file
            deleteAllAccounts();

            String deletedAccountName = new String();       // The password being deleted.
            String deletedAccountPassword = new String();   // The username being deleted.

            // Open BackupAccounts file for reading
            FileReader fr = new FileReader("BackupAccounts.txt");
            Scanner scan = new Scanner(fr);
            // Open Accounts file for writing
            FileWriter fw = new FileWriter("Accounts.txt", true);
            BufferedWriter out = new BufferedWriter(fw);

            while (scan.hasNext()){
                StringTokenizer st = new StringTokenizer(scan.nextLine(), "\t");
                String tempToken = st.nextToken();

                // If name is found, store name and password into temporary
                // variables that will not be used.
                if (tempToken.equals(name)){
                    deletedAccountName = tempToken;
                    deletedAccountPassword = st.nextToken();
                }
                // If name is found, write the name and password to the
                // Accounts.txt file.
                else{
                    String tempPlayerPassword = st.nextToken();
                    out.write(tempToken + "\t" + tempPlayerPassword);
                    out.newLine();
                }
            }

            out.close();
            scan.close();
        }
        // If the player does not exist, do not remove any accounts.
        // Print error message.
        else
            JOptionPane.showMessageDialog(null, "The account for " + name
                    + " cannot be removed\nbecause it does not exist.");
    }

    /**
     * Returns all of the player names and passwords from the accounts file.
     *
     * @return String The combined names of all the players.
     */
    static public String findAllPlayers() throws FileNotFoundException{
        FileReader fr = new FileReader("Accounts.txt");
        Scanner scan = new Scanner(fr);

        String players = new String();

        while (scan.hasNext()){
            StringTokenizer st = new StringTokenizer(scan.nextLine(), " ");
            players += (showPlayerName(st.nextToken()) + " ");
        }

        scan.close();
        return players;
    }

    /**
     * This is called from another function to return the player's name.
     *
     * @param token A player's username.
     * @return String Returns a player's username.
     */
    static public String showPlayerName(String name){
        return name;
    }

    /**
     * Returns a string of information about this class containing
     * the class name.
     *
     * @param username A player's username.
     * @return boolean Returns true if the player is found in the accounts file
     * and false otherwise.
     */
    static public boolean doesPlayerExist(String name) throws FileNotFoundException{
        FileReader fr = new FileReader("Accounts.txt");
        Scanner scan = new Scanner(fr);

        boolean flag = false;

        while (scan.hasNextLine()){
            StringTokenizer st = new StringTokenizer(scan.nextLine(), "\t");
            if (st.nextToken().equals(name)){
                flag = true;
                break;
            }
        }

        scan.close();
        return flag;
    }

    /**
     * Loads a player object based on a username. Returns null if the player
     * does not exist.
     *
     * @param username A player's username.
     * @return Loaded player object.
     */
    static public Player loadPlayer(String username){
        Player player = null;

        try {
        if(doesPlayerExist(username))
                player = new Player(username, getPlayerPassword(username));
        } catch(Exception err) {
            //do nothing.
        }

        return player;
    }

    /**
     * Returns a given player's password.
     *
     * @param username A player's username.
     * @return String Returns the player's password.
     */
    static public String getPlayerPassword(String username) throws FileNotFoundException{
        // Open the Accounts.txt file for reading.
        FileReader fr = new FileReader("Accounts.txt");
        Scanner scan = new Scanner(fr);

        boolean flag = false;
        String password = new String();

        while (scan.hasNextLine()){
            StringTokenizer st = new StringTokenizer(scan.nextLine(), "\t");
            // If the player's name was found, set the flag to true, and
            // retrieve the player's password.
            if (st.nextToken().equals(username)){
                flag = true;
                password = st.nextToken();
                break;
            }
        }

        scan.close();
        return password;
    }

    /**
     * Deletes the entire accounts file.
     *
     * @param password A player's unencrypted password.
     */
    static public void createPasswordHash(String password){
        int i;
        long hash = 0;
        String newPassword = new String();

        for (i = 0; i < password.length(); i++){
            hash = (password.charAt(i) << 2);
            newPassword += hash;
        }
    }

    /**
     * Deletes the entire accounts file.
     */
    static public void deleteAllAccounts() throws IOException{
        FileWriter fw = new FileWriter("Accounts.txt", false);
        fw.close();
    }
    
    /**
     * Deletes the entire backup accounts file.
     */
    static public void deleteBackupAccounts() throws IOException{
        FileWriter fw = new FileWriter("BackupAccounts.txt", false);
        fw.close();
    }

    /**
     * Creates a backup of the accounts file.
     */
    static public void createBackupAccountsFile() throws IOException{
        deleteBackupAccounts();

        // Open the Accounts.txt file for reading only.
        FileReader fr = new FileReader("Accounts.txt");
        Scanner scan = new Scanner(fr);
        // Open the BackupAccounts.txt file for appending.
        FileWriter fw = new FileWriter("BackupAccounts.txt", true);
        BufferedWriter out = new BufferedWriter(fw);

        // Copy the each line from the Accounts.txt file to the
        // BackupAccounts.txt file.
        while (scan.hasNext()){
            out.write(scan.nextLine());
            out.newLine();
        }

        scan.close();
        out.close();
    }
}